package com.liy.cloud.common.pw.service.impl;

import com.liy.cloud.common.pw.dao.PwAccountListDao;
import com.liy.cloud.common.pw.dao.PwAccountMainDao;
import com.liy.cloud.common.pw.dao.PwPayNoticeDao;
import com.das.cloud.osc.common.pw.entity.*;
import com.das.cloud.osc.common.pw.service.*;
import com.liy.cloud.common.pw.entity.*;
import com.liy.cloud.common.pw.service.*;
import com.liy.cloud.common.pw.utils.PwConstant;
import com.liy.cloud.common.pw.vo.GoodsPropertyMoneydetailVO;

import com.das.framework.common.dao.IBaseDao;
import com.das.framework.common.exception.BusinessException;
import com.das.framework.common.service.impl.BaseServiceImpl;
import com.das.framework.common.utils.DateUtil;
import com.das.framework.common.utils.Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: liyang
 * @Date: 2018/7/20 11:04
 * @Description:  serviceImpl - 管理票款
 **/
@Service
public class PwAccountMainTicketMoneyServiceImpl extends BaseServiceImpl<PwAccountMainEntity, String> implements PwAccountMainTicketMoneyService {

    @Autowired
    private PwAccountMainDao accountMainDao;

    @Autowired
    private PwAccountListDao accountListDao;

    @Autowired
    private PwPayNoticeDao pwPayNoticeDao;

    @Autowired
    private PwAccountMainService accountMainService;

    @Autowired
    private PwSystemStorageService systemStorageService;

    @Autowired
    private PwAccountListService accountListService;

    @Autowired
    private PwAccountMoneydetailService pwAccountMoneydetailService;

    @Autowired
    private PwAccountBillService accountBillService;

    @Override
    public IBaseDao<PwAccountMainEntity, String> getDao() {
        return accountMainDao;
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/4  15:06
     * @Description: 新增票款配发: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage, 出库操作
     **/
    @Override
    public void addAllocateTicketMoney(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 出库
        accountMainService.takeOutPwSystemStorage(mainEntity, list);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/23  16:18
     * @Description: 作废票款配发
     * @params: accountId 要作废的单据编号
     **/
    @Override
    public void invalidAllocateTicketMoney(String accountId) throws Exception{
        // 作废入库
        accountMainService.invalidInSystemStorage(accountId);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/10  17:22
     * @Description: 新增预收款: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage, 入库操作
     **/
    @Override
    public void addAdvanceReceived(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 入库
        accountMainService.putInPwSystemStorage(mainEntity, list);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/23  16:42
     * @Description: 作废预收款
     * @params: accountId 要作废的单据编号
     **/
    public void invalidAdvanceReceived(String accountId) throws Exception{
        // 作废出库
        accountMainService.invalidOutSystemStorage(accountId);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/11  17:12
     * @Description: 新增上交票款: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage, 入库操作
     **/
    @Override
    public void addHandIn(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 入库
        accountMainService.putInPwSystemStorage(mainEntity, list);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/23  16:59
     * @Description: 作废上交票款
     * @params: accountId 要作废的单据编号
     **/
    @Override
    public void invalidHandIn(String accountId) throws Exception{
        // 作废出库
        accountMainService.invalidOutSystemStorage(accountId);
    }

    @Override
    public void addShortMoney(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 单据编号
        mainEntity.setAccountId(accountMainService.generateAccountId(mainEntity));
        // 新增 主表Mian
        accountMainDao.insertSelective(mainEntity);

        // 明细List
        for (PwAccountListEntity listEntity : list) {
            listEntity.setId(Tools.getNewUUID());
            // 主单据编号
            listEntity.setAccountId(mainEntity.getAccountId());
            // 车站编号
            listEntity.setSystemId(mainEntity.getSystemId());
            // 单据类型
            listEntity.setType(mainEntity.getType());
            // 新增 明细List
            accountListService.add(listEntity);
        }
    }

    @Override
    public void auditShortMoney(String accountId) throws Exception {

        PwAccountMainEntity mainEntity = accountMainService.selectByAccountId(accountId);
        if(mainEntity == null){
            throw new BusinessException("查询不到编号为：“" + accountId + "”的短款补款单据！");
        }

        // 查询关联的交接班记录
        PwAccountMainEntity jiaoJieMainEntity = accountMainDao.selectByAccountId(mainEntity.getExt4());
        if(jiaoJieMainEntity == null){
            throw new BusinessException("查询不到编号为：“" + mainEntity.getExt4() + "” 的交接班单据！");
        }
        if(Tools.StringIsNullOrSpace(jiaoJieMainEntity.getExt4())){
            jiaoJieMainEntity.setExt4("0");
        }
        if(Tools.StringIsNullOrSpace(jiaoJieMainEntity.getExt3())){
            jiaoJieMainEntity.setExt3("0");
        }

        double actMoney = 0; // 暂时记录, 待需求明确后再做修改

        List<PwAccountListEntity> list = accountListService.getListByAccountId(accountId);
        // 明细List 流水Bill 和 库存Storage
        for (PwAccountListEntity listEntity : list) {
            // 如果备用金短款补款金额或者票款短款补款金额为0，则无票务单据明细信息和票务单据出入库信息，客值也不需要输入实际的补款金额。
            if(listEntity.getActMoney() == null || listEntity.getActMoney() == 0){
                continue;
            }
            // 更新/添加的库存，先查询库存总量，计算实际库存。
            PwSystemStorageEntity storageEntity = systemStorageService.queryStorageBySystemIdAndItemId(listEntity.getSystemId(), listEntity.getItemId());
            // 库存中没有则抛出异常
            if(storageEntity == null){
                throw new BusinessException("第" + listEntity.getSeq() + "行：该物品库存中不存在！");
            }else { // 库存中已经存在则更新
                // 设置当前金额
                storageEntity.setCurrentMoney(storageEntity.getCurrentMoney() - listEntity.getActMoney());
                // 更新前检测库存金额
                if (storageEntity.getCurrentMoney() !=null && storageEntity.getCurrentMoney() < 0) {
                    throw new BusinessException("第" + listEntity.getSeq() + "行：更新库存失败，库存金额不能小于0！");
                }
                // 更新库存
                systemStorageService.updateBySystemIdAndItemId(storageEntity);
            }

            // 流水bill，操作类型：审核，出入库标识：出库
            accountMainService.addAccountBill(mainEntity, listEntity, storageEntity, PwConstant.BILL_OPER_TYPE_CHECK, PwConstant.BILL_INOUT_TYPE_OUT);

            switch (listEntity.getItemId()){
                case "M01": // 单据审核后，系统会读取单据明细里面的备用金实际补款金额，累计更新到关联的客值交接班主表信息里面的备用字段4里。（读取之前的值，本次更新的值为之前值 + 备用金实际补款金额）
                    actMoney = listEntity.getActMoney();
                    jiaoJieMainEntity.setExt4(String.valueOf(Double.valueOf(jiaoJieMainEntity.getExt4()) + listEntity.getActMoney()));
                case "M02": // 单据审核后，系统会读取单据明细里面的票款实际补款金额，累计更新到关联的客值交接班主表信息里面的备用字段3里。（读取之前的值，本次更新的值为之前值 + 票款实际补款金额）
                    jiaoJieMainEntity.setExt3(String.valueOf(Double.valueOf(jiaoJieMainEntity.getExt3()) + listEntity.getActMoney()));
            }
        }
        // 更新交接班主表
        accountMainDao.updateMainEntityBtAccountId(jiaoJieMainEntity);
        PwPayNoticeEntity pwPayNoticeEntity = new PwPayNoticeEntity();
        pwPayNoticeEntity.setId(mainEntity.getRelateId());
        // 单据审核后，需要在车站修改中心的短款补款通知单里单据的单据处理标识为03：车站已处理。
        pwPayNoticeEntity.setDealF("03");
        pwPayNoticeEntity.setM02num(actMoney); // 暂时m02表示实际补款金额，需根据需求修改
        pwPayNoticeDao.updateByPrimaryKeySelective(pwPayNoticeEntity);
        // 主单据状态改为已审核
        mainEntity.setStatus(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
        accountMainDao.updateMainEntityBtAccountId(mainEntity);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/17  16:37
     * @Description: 作废短款补款: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage, 回滚操作
     **/
    @Override
    public void invalidShortMoney(String accountId) throws Exception {

        // 查询单据，将状态更新为作废
        PwAccountMainEntity mainEntity = accountMainDao.selectByAccountId(accountId);
        if (mainEntity == null) {
            throw new BusinessException("查询不到编号为：“" + accountId + "” 的的单据！");
        }
        mainEntity.invalid();
        accountMainDao.updateMainEntityBtAccountId(mainEntity);

        if(PwConstant.PW_ACCOUNTID_STATUS_CHECK.equals(mainEntity.getStatus())){
            // 审核后的单据作废后，需要对原来关联的客值交接班主表信息里面的备用字段3和备用字段4字段进行回滚。
            List<PwAccountListEntity> list = accountListDao.getListByAccountId(accountId);
            // 查询关联的交接班记录
            PwAccountMainEntity jiaoJieMainEntity = accountMainDao.selectByAccountId(mainEntity.getExt4());
            if (jiaoJieMainEntity == null) {
                throw new BusinessException("查询不到编号为：“" + mainEntity.getExt4() + "” 的交接班单据！");
            }
            if (Tools.StringIsNullOrSpace(jiaoJieMainEntity.getExt4())) {
                jiaoJieMainEntity.setExt4("0");
            }
            if (Tools.StringIsNullOrSpace(jiaoJieMainEntity.getExt3())) {
                jiaoJieMainEntity.setExt3("0");
            }
            // 流水Bill 和 库存Storage
            for (PwAccountListEntity listEntity : list) {
                // 如果备用金短款补款金额或者票款短款补款金额为0，则无票务单据明细信息和票务单据出入库信息。
                if (listEntity.getActMoney() == null || listEntity.getActMoney() == 0) {
                    continue;
                }
                // 更新的库存，先查询库存总量，计算实际库存。
                PwSystemStorageEntity storageEntity = systemStorageService.queryStorageBySystemIdAndItemId(listEntity.getSystemId(), listEntity.getItemId());
                // 库存中没有则作废失败
                if (storageEntity == null) {
                    throw new BusinessException("找不到编号为：“" + listEntity.getItemId() + "” 的物品库存！");
                } else { // 库存中已经存在则更新
                    // 设置当前金额
                    storageEntity.setCurrentMoney(storageEntity.getCurrentMoney() + listEntity.getActMoney());
                    // 更新前检测库存金额
                    if (storageEntity.getCurrentMoney() != null && storageEntity.getCurrentMoney() < 0) {
                        throw new BusinessException("编号为：“" + listEntity.getItemId() + "”的库存金额不能小于0！");
                    }
                    // 更新库存
                    systemStorageService.updateBySystemIdAndItemId(storageEntity);
                }

                // 流水bill，操作类型：作废，出入库标识：入库
                accountMainService.addAccountBill(mainEntity, listEntity, storageEntity, PwConstant.BILL_OPER_TYPE_INVALID, PwConstant.BILL_INOUT_TYPE_IN);

                switch (listEntity.getItemId()) {
                    case "M01": // 单据作废后，根据单据明细里面的备用金实际补款金额，回滚关联的客值交接班主表信息里面的备用字段4。（读取之前的值，本次更新的值为之前值 - 备用金实际补款金额）
                        jiaoJieMainEntity.setExt4(String.valueOf(Double.valueOf(jiaoJieMainEntity.getExt4()) - listEntity.getActMoney()));
                    case "M02": // 单据作废后，根据单据明细里面的票款实际补款金额，回滚关联的客值交接班主表信息里面的备用字段3。（读取之前的值，本次更新的值为之前值 - 票款实际补款金额）
                        jiaoJieMainEntity.setExt3(String.valueOf(Double.valueOf(jiaoJieMainEntity.getExt3()) - listEntity.getActMoney()));
                }
            }
            // 更新交接班主表
            accountMainDao.updateMainEntityBtAccountId(jiaoJieMainEntity);
        }
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/11  15:16
     * @Description: 新增异常票款登记: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage, 入库操作
     **/
    @Override
    public void addAbnormalMoney(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 入库
        accountMainService.putInPwSystemStorage(mainEntity, list);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/23  17:50
     * @Description: 作废异常票款
     * @params: accountId 要作废的单据编号
     **/
    @Override
    public void invalidAbnormalMoney(String accountId) throws Exception{
        // 作废出库
        accountMainService.invalidOutSystemStorage(accountId);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/20 10:54
     * @Description: 新增解行现金登记: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage, 出库操作
     **/
    @Override
    public void addPayingBankMoney(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 单据编号
        mainEntity.setAccountId(accountMainService.generateAccountId(mainEntity));
        // 1.新增 主表Mian
        accountMainDao.insertSelective(mainEntity);
        // 明细List
        for (PwAccountListEntity listEntity : list) {
            // 设置明细表主键
            listEntity.setId(Tools.getNewUUID());
            // 主单据编号
            listEntity.setAccountId(mainEntity.getAccountId());
            // 单据类型
            listEntity.setType(mainEntity.getType());
            // 车站编号
            listEntity.setSystemId(mainEntity.getSystemId());
            // 2.新增 明细List
            accountListService.add(listEntity);
        }
    }

    @Override
    public void auditPayingBankMoney(String accountId) throws Exception {
        PwAccountMainEntity mainEntity = accountMainService.selectByAccountId(accountId);
        mainEntity.setCheckDate(DateUtil.getTimeNow());
        List<PwAccountListEntity> list = accountListService.getListByAccountId(accountId);
        // 库存缓存列表，多次更新同一条库存时先缓存上一次更新过的记录
        List<PwSystemStorageEntity> cacheList = new ArrayList<>();
        // 明细List 流水Bill 和 库存Storage
        for (PwAccountListEntity listEntity : list) {
            // 更新的库存，先查询库存总量，计算实际库存
            PwSystemStorageEntity storageEntity = null;
            // 先从缓存列表中查询
            for (PwSystemStorageEntity entity : cacheList) {
                if (entity.getSystemId().equals(listEntity.getSystemId()) && entity.getItemId().equals(listEntity.getItemId())) {
                    storageEntity = entity;
                    break;
                }
            }
            // 如果缓存列表中不存在，从数据库中查询
            if (storageEntity == null) {
                storageEntity = systemStorageService.queryStorageBySystemIdAndItemId(listEntity.getSystemId(), listEntity.getItemId());
                // 如果数据库中也没有则抛出异常
                if (storageEntity == null) {
                    throw new BusinessException("第" + listEntity.getSeq() + "行：该物品库存中不存在！");
                }
                // 更新的库存加入缓存列表
                cacheList.add(storageEntity);
            }
            // 设置当前金额
            if (listEntity.getActMoney() != null && listEntity.getActMoney() != 0 && storageEntity.getCurrentMoney() != null) {
                storageEntity.setCurrentMoney(storageEntity.getCurrentMoney() - listEntity.getActMoney());
            }
            // 设置当前数量
            if (listEntity.getActNum() != null && listEntity.getActNum() != 0 && storageEntity.getCurrentNum() != null) {
                storageEntity.setCurrentNum(storageEntity.getCurrentNum() - listEntity.getActNum());
            }
            // 更新前检测库存金额
            if (storageEntity.getCurrentMoney() != null && storageEntity.getCurrentMoney() < 0) {
                throw new BusinessException("第" + listEntity.getSeq() + "行：库存金额不足！");
            }
            // 更新前检测库存数量
            if (storageEntity.getCurrentNum() != null && storageEntity.getCurrentNum() < 0) {
                throw new BusinessException("第" + listEntity.getSeq() + "行：库存数量不足！");
            }
            // 3.库存storage变动
            systemStorageService.updateBySystemIdAndItemId(storageEntity);

            // 流水bill，操作类型：审核，出入库标识：出库
            accountMainService.addAccountBill(mainEntity, listEntity, storageEntity, PwConstant.BILL_OPER_TYPE_CHECK, PwConstant.BILL_INOUT_TYPE_OUT);
        }
        mainEntity.setStatus(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
        accountMainService.update(mainEntity);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/20  10:50
     * @Description: 新增上日实际解行登记，上日实际解行单据仅仅是录入具体的解行情况结果，不涉及车站库存的变更；
     *  单据审核后，需要更新对应的现金解行单据，备用字段2修改为已关联，备用字段3更新为本上日实际解行单据的单据编号。
     * @params: mainEntity:主体单据   list:明细列表
     **/
    @Override
    public void addRealPayingBank(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 单据编号
        mainEntity.setAccountId(accountMainService.generateAccountId(mainEntity));
        // 新增 主表Mian
        accountMainDao.insertSelective(mainEntity);
        // 新增 明细List
        for (PwAccountListEntity listEntity : list) {
            listEntity.setId(Tools.getNewUUID());
            // 主单据编号
            listEntity.setAccountId(mainEntity.getAccountId());
            // 单据类型
            listEntity.setType(mainEntity.getType());
            accountListService.add(listEntity);
        }
        // 查询对应的现金解行单据
        PwAccountMainEntity jieHangMainEntity = accountMainDao.selectByAccountId(mainEntity.getRelateId());
        if (jieHangMainEntity != null) {
            // 备用字段2修改为已关联（0：未关联  1：已经关联）
            jieHangMainEntity.setExt2("1");
            // 备用字段3更新为本上日实际解行单据的单据编号
            jieHangMainEntity.setExt3(mainEntity.getAccountId());
            // 更新对应的现金解行单据
            accountMainDao.updateMainEntityBtAccountId(jieHangMainEntity);
        }
    }

    @Override
    public void auditRealPayingBank(String accountId) throws Exception {
        PwAccountMainEntity mainEntity = accountMainService.selectByAccountId(accountId);
        mainEntity.setCheckDate(DateUtil.getTimeNow());
        mainEntity.setStatus(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
        accountMainService.update(mainEntity);
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/23  11:10
     * @Description: 作废解行现金单
     * @params: accountId 要作废的单据编号
     **/
    @Override
    public void invalidPayingBankMoney(String accountId) throws Exception {

        // 查询解行现金单据
        PwAccountMainEntity mainEntity = accountMainDao.selectByAccountId(accountId);
        if (mainEntity == null) {
            throw new BusinessException("查询不到编号为：“" + accountId + "” 的单据！");
        }
        // 判断扩展字段ext2，如果已关联上日实解单则不允许作废，0：未关联 1：已经关联
        if (mainEntity.getExt2() == "1") {
            throw new BusinessException("单据：“" + accountId + "” 已经关联了上日实解单：“" + mainEntity.getExt3() + "”，不能作废！");
        }
        // 单据作废
        mainEntity.invalid();
        // 更新单据
        accountMainDao.updateMainEntityBtAccountId(mainEntity);
        // 查询明细，回滚库存（入库操作）
        List<PwAccountListEntity> list = accountListDao.getListByAccountId(accountId);
        for (PwAccountListEntity listEntity : list) {
            // 查询库存
            PwSystemStorageEntity storageEntity = systemStorageService.queryStorageBySystemIdAndItemId(listEntity.getSystemId(), listEntity.getItemId());
            if (storageEntity == null) {
                throw new BusinessException("找不到编号为：“" + listEntity.getItemId() + "” 的物品库存！");
            }
            // 计算库存
            storageEntity.setCurrentMoney(storageEntity.getCurrentMoney() + listEntity.getActMoney());
            // 更新前检测库存金额
            if (storageEntity.getCurrentMoney() != null && storageEntity.getCurrentMoney() < 0) {
                throw new BusinessException("编号为：“" + listEntity.getItemId() + "”的库存金额不能小于0！");
            }
            // 更新库存
            systemStorageService.updateBySystemIdAndItemId(storageEntity);
            // 流水记录 操作类型：作废 出入库标识：入库
            accountMainService.addAccountBill(mainEntity, listEntity, storageEntity, PwConstant.BILL_OPER_TYPE_INVALID, PwConstant.BILL_INOUT_TYPE_IN);
        }
    }

    /*
     * @Author:  libs
     * @Date:    2018/7/23  14:16
     * @Description: 作废上日实际解行单
     * @params: accountId 要作废的单据编号
     **/
    @Override
    public void invalidRealPayingBank(String accountId) throws Exception {
        // 查询上日解行单
        PwAccountMainEntity mainEntity = accountMainDao.selectByAccountId(accountId);
        if (mainEntity == null) {
            throw new BusinessException("查询不到编号为：“" + accountId + "” 的单据！");
        }
        // 单据作废
        mainEntity.invalid();
        // 更新单据
        accountMainDao.updateMainEntityBtAccountId(mainEntity);
        // 单据作废后，需要回退对应的现金解行单据备用字段2和备用字段3的状态。
        // 查询对应的现金解行单
        PwAccountMainEntity jieHangMainEntity = accountMainDao.selectByAccountId(mainEntity.getRelateId());
        // 关联上日实解单，0：未关联 1：已经关联
        jieHangMainEntity.setExt2("0");
        // 关联的上日实解单单号
        jieHangMainEntity.setExt3("");
        // 更新现金解行单
        accountMainDao.updateMainEntityBtAccountId(jieHangMainEntity);
    }

    /*
     * @Author:         zhangw
     * @CreateDate:     2018/7/5 16:20
     * @Description:    新增设备补币: 主表单Mian, 明细list, 出入库记录流水Bill, 库存信息Storage  金额明细moneydetail
     */
    @Override
    public void addequReplenPlan(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws BusinessException, Exception {

        //单据编号
        String accountId = accountMainService.generateAccountId(mainEntity);
        mainEntity.setAccountId(accountId);
        // 1.新增 主表Mian
        accountMainDao.insertSelective(mainEntity);
        // 2.新增 明细List
        for (PwAccountListEntity listEntity : list) {
            // 查询条件，查询当前运营日内进行了补币操作的设备
            PwAccountListEntity listEntityQuery = new PwAccountListEntity();
            // 车站编号
            listEntityQuery.setSystemId(mainEntity.getSystemId());
            // 单据类型，补币
            listEntityQuery.setType(PwConstant.SCAccountIdRole.BU_BI);
            // 单据状态，已审核
            listEntityQuery.setTempField(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
            // 审核时间，当前运营日
            listEntityQuery.setCreateDate(DateUtil.getTimeNow());
            // 设备编号
            listEntityQuery.setDeviceId(listEntity.getDeviceId());
            // 查询信息，判断相关设备当前运营日内是否进行了补币操作
            List<PwAccountListEntity> buBiList = accountListService.getOneDayList(listEntityQuery);
            if (buBiList != null && !buBiList.isEmpty()) {
                throw new BusinessException("第" + listEntity.getSeq() + "行：设备编号为：" + listEntity.getDeviceId() + " 的设备在当前运营日内已经完成了补币操作，不允许再次补币!");
            }
            // 5.保存金额明细
            List<GoodsPropertyMoneydetailVO> moneyDtlList = listEntity.getMoneyDtl();
            if (moneyDtlList != null) {
                for (GoodsPropertyMoneydetailVO moneyDtlVO : moneyDtlList) {
                    PwAccountMoneyDetailEntity entity = new PwAccountMoneyDetailEntity();
                    entity.setId(Tools.getNewUUID());
                    entity.setSystemid(mainEntity.getSystemId());
                    entity.setAccountid(mainEntity.getAccountId());
                    entity.setType(mainEntity.getType());
                    entity.setDeviceid(listEntity.getDeviceId());
                    entity.setMoneytype(moneyDtlVO.getMoneytype());
                    entity.setMoneyamount(moneyDtlVO.getItemamount());
                    entity.setMoneynum(moneyDtlVO.getMoneynum());
                    entity.setMoneytotal(moneyDtlVO.getMoneytotal().doubleValue());
                    pwAccountMoneydetailService.add(entity);
                }
            }
            listEntity.setId(Tools.getNewUUID());
            listEntity.setSystemId(mainEntity.getSystemId());
            // 主单据编号
            listEntity.setAccountId(mainEntity.getAccountId());
            //单据类型
            listEntity.setType(mainEntity.getType());
            listEntity.setItemId("M01");//备用金
            listEntity.setValidTime(DateUtil.getStringDateShort());
            listEntity.setItemStatus(PwConstant.STATUS_YES_1);//单据状态有效
            accountListService.add(listEntity);
        }
    }

    @Override
    public void auditEquReplenPlan(String accountId) throws Exception {
        PwAccountMainEntity mainEntity = accountMainService.selectByAccountId(accountId);
        mainEntity.setCheckDate(DateUtil.getTimeNow());
        List<PwAccountListEntity> list = accountListService.getListByAccountId(accountId);
        // 流水Bill 和 库存Storage
        Double num = 0.0;
        for (PwAccountListEntity listEntity : list) {
            num = num + listEntity.getActMoney();
        }
        //先查询库存总金额 - 补币金额  = 实际金额
        PwSystemStorageEntity pwSystemStorageEntity = systemStorageService.queryStorageBySystemIdAndItemId(mainEntity.getSystemId(), "M01");
        PwSystemStorageEntity storageEntity = new PwSystemStorageEntity();
        // 车站编号
        storageEntity.setSystemId(mainEntity.getSystemId());
        // 物品ID
        storageEntity.setItemId("M01");//备用金
        // 设置当前金额
        storageEntity.setCurrentMoney(pwSystemStorageEntity.getCurrentMoney() - num);
        if (storageEntity.getCurrentMoney() < 0) {
            throw new BusinessException("补币金额大于库存金额,总库存为：" + pwSystemStorageEntity.getCurrentMoney() + "元！");
        }
        //3.库存storage变动
        systemStorageService.updateBySystemIdAndItemId(storageEntity);

        //流水bill
        PwAccountBillEntity billEntity = new PwAccountBillEntity();
        // ID
        billEntity.setId(Tools.getNewUUID());
        // 车站编号
        billEntity.setSystemId(mainEntity.getSystemId());
        // Bill 单据编号
        billEntity.setAccountId(mainEntity.getAccountId());
        // 单据类型 (查数据字典) 车站客值交接班记录: 24
        billEntity.setType(mainEntity.getType());
        // 物品Id
        billEntity.setItemId("M01");//备用金
        // 物品状态
        billEntity.setStatus(PwConstant.STATUS_YES_1);
        //操作类型 (查数据字典)  审核: 2
        billEntity.setOperType(PwConstant.BILL_OPER_TYPE_CHECK);
        //出入库标识//出库
        billEntity.setInoutF(PwConstant.BILL_INOUT_TYPE_OUT);
        //操作金额
        billEntity.setOperMoney(num);
        //剩余金额 == 实际金额
        billEntity.setMoneyLeft(storageEntity.getCurrentMoney());

        //审核员 == Main主表的审核人
        billEntity.setCheckOper(mainEntity.getCheckOper());
        //审核时间
        billEntity.setCheckDate(mainEntity.getCheckDate());
        // 4.出入库流水记录bill
        accountBillService.add(billEntity);

        mainEntity.setStatus(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
        accountMainService.update(mainEntity);
    }

    /**
     * 作废设备补币
     *
     * @param mainEntity 单据主表
     * @throws Exception
     */
    @Override
    public void invalidequReplenPlan(PwAccountMainEntity mainEntity) throws Exception {

        //更新作废状态
        accountMainDao.updateMainEntityBtAccountId(mainEntity);
        //查询明细
        List<PwAccountListEntity> list = accountListService.getListByAccountId(mainEntity.getAccountId());
        //修改库存
        // 流水Bill 和 库存Storage
        Double num = 0.0;
        for (PwAccountListEntity listEntity : list) {
            num = num + (Double) listEntity.getActMoney();
        }

        //先查询库存总金额 - 补币金额  = 实际金额
        PwSystemStorageEntity pwSystemStorageEntity = systemStorageService.queryStorageBySystemIdAndItemId(mainEntity.getSystemId(), "M01");
        PwSystemStorageEntity storageEntity = new PwSystemStorageEntity();
        // 车站编号
        storageEntity.setSystemId(mainEntity.getSystemId());
        // 物品ID
        storageEntity.setItemId("M01");//备用金
        // 设置当前金额
        storageEntity.setCurrentMoney(pwSystemStorageEntity.getCurrentMoney() + num);
        //3.库存storage变动
        systemStorageService.updateBySystemIdAndItemId(storageEntity);


        //流水bill
        PwAccountBillEntity billEntity = new PwAccountBillEntity();
        // ID
        billEntity.setId(Tools.getNewUUID());
        // 车站编号
        billEntity.setSystemId(mainEntity.getSystemId());
        // Bill 单据编号
        billEntity.setAccountId(mainEntity.getAccountId());
        // 单据类型 (查数据字典) 车站客值交接班记录: 24
        billEntity.setType(mainEntity.getType());
        // 物品Id
        billEntity.setItemId("M01");//备用金
        // 物品状态
        billEntity.setStatus(PwConstant.STATUS_YES_1);
        //操作类型 (查数据字典)  作废
        billEntity.setOperType(PwConstant.BILL_OPER_TYPE_INVALID);
        //出入库标识 入库
        billEntity.setInoutF(PwConstant.BILL_INOUT_TYPE_IN);
        //操作金额
        billEntity.setOperMoney(num);
        //剩余金额 == 实际金额
        billEntity.setMoneyLeft(storageEntity.getCurrentMoney());

        //审核员 == Main主表的作废人
        billEntity.setCheckOper(mainEntity.getInvalidOper());
        //审核时间
        billEntity.setCheckDate(DateUtil.getTimeNow());
        // 4.出入库流水记录bill
        accountBillService.add(billEntity);

    }

    /*
     * @Author:  libs
     * @Date:    2018/8/3  15:56
     * @Description: 新增回收设备票款，入库操作
     * @params: mainEntity:主体单据   list:明细列表
     **/
    @Override
    public void addCollectEquipmentMoney(PwAccountMainEntity mainEntity, List<PwAccountListEntity> list) throws Exception {
        // 单据编号
        mainEntity.setAccountId(accountMainService.generateAccountId(mainEntity));

        // 票款入库总额
        double totalM02 = 0;
        // 物品类型 票款类
        String itemType = "01";
        // 物品ID 票款
        String itemId = "M02";
        // 明细List 流水Bill 和 库存Storage
        for (PwAccountListEntity listEntity : list) {
            // 查询条件，查询当前运营日内进行了补币操作的设备
            PwAccountListEntity listEntityQuery = new PwAccountListEntity();
            // 车站编号
            listEntityQuery.setSystemId(mainEntity.getSystemId());
            // 单据类型，补币
            listEntityQuery.setType(PwConstant.SCAccountIdRole.BU_BI);
            // 单据状态，已审核
            listEntityQuery.setTempField(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
            // 审核时间，当前运营日
            listEntityQuery.setCreateDate(DateUtil.getTimeNow());
            // 设备编号
            listEntityQuery.setDeviceId(listEntity.getDeviceId());
            // 查询信息，判断相关设备当前运营日内是否进行了补币操作
            List<PwAccountListEntity> buBiList = accountListService.getOneDayList(listEntityQuery);
            if (buBiList == null || buBiList.isEmpty()) {
                throw new BusinessException("第" + listEntity.getSeq() + "行：设备编号为：" + listEntity.getDeviceId() + " 的设备在当前运营日内未进行补币操作，不能回收设备票款！");
            }
            // 单据类型，钱清
            listEntityQuery.setType(PwConstant.SCAccountIdRole.QIAN_QING);
            // 查询信息，判断相关设备当前运营日内是否进行了钱箱清空清点的操作
            List<PwAccountListEntity> qingKongList = accountListService.getOneDayList(listEntityQuery);
            if (qingKongList != null && !qingKongList.isEmpty()) {
                throw new BusinessException("第" + listEntity.getSeq() + "行：设备编号为：" + listEntity.getDeviceId() + " 的设备在当前运营日内已经完成钱箱清空清点操作，不能回收设备票款！");
            }
            // 设置明细表主键
            listEntity.setId(Tools.getNewUUID());
            // 主单据编号
            listEntity.setAccountId(mainEntity.getAccountId());
            // 单据类型
            listEntity.setType(mainEntity.getType());
            listEntity.setItemType(itemType);
            listEntity.setItemId(itemId);
            // 计算票款入库总额
            totalM02 += listEntity.getActMoney();
            // 新增 明细List
            accountListService.add(listEntity);

            // 保存金额明细
            List<GoodsPropertyMoneydetailVO> moneyDtlList = listEntity.getMoneyDtl();
            for (GoodsPropertyMoneydetailVO moneyDtlVO : moneyDtlList) {
                PwAccountMoneyDetailEntity entity = new PwAccountMoneyDetailEntity();
                entity.setId(Tools.getNewUUID());
                entity.setSystemid(listEntity.getSystemId());
                entity.setAccountid(listEntity.getAccountId());
                entity.setType(listEntity.getType());
                entity.setDeviceid(listEntity.getDeviceId());
                entity.setMoneytype(moneyDtlVO.getMoneytype());
                entity.setMoneyamount(moneyDtlVO.getItemamount());
                entity.setMoneynum(moneyDtlVO.getMoneynum());
                entity.setMoneytotal(moneyDtlVO.getMoneytotal().doubleValue());
                pwAccountMoneydetailService.add(entity);
            }
        }
        // 保存入库总额，审核/作废时可以直接使用。
        mainEntity.setExt2(String.valueOf(totalM02));
        // 新增 主表Mian
        accountMainDao.insertSelective(mainEntity);
    }

    @Override
    public void auditCollectEquipmentMoney(String accountId) throws Exception{
        PwAccountMainEntity mainEntity = accountMainService.selectByAccountId(accountId);
        mainEntity.setCheckDate(DateUtil.getTimeNow());

        // 票款入库总额
        double totalM02 = Double.valueOf(mainEntity.getExt2());
        // 物品类型 票款类
        String itemType = "01";
        // 物品ID 票款
        String itemId = "M02";
        // 明细List 流水Bill 和 库存Storage
        // 票款入库
        // 更新的库存，先查询库存总量，计算实际库存
        PwSystemStorageEntity storageEntity = systemStorageService.queryStorageBySystemIdAndItemId(mainEntity.getSystemId(), itemId);
        // 如果库存中不存在备用金则新增一条记录
        if (storageEntity == null) {
            storageEntity = new PwSystemStorageEntity();
            // 库存编号
            storageEntity.setId(Tools.getNewUUID());
            // 车站编号
            storageEntity.setSystemId(mainEntity.getSystemId());
            // 物品编号
            storageEntity.setItemId(itemId);
            // 物品类型
            storageEntity.setType(itemType);
            // 物品状态
            storageEntity.setStatus("1");
            // 设置当前金额
            storageEntity.setCurrentMoney(totalM02);
            // 新增库存
            systemStorageService.add(storageEntity);
        } else {
            // 设置当前金额
            if (storageEntity.getCurrentMoney() != null) {
                storageEntity.setCurrentMoney(storageEntity.getCurrentMoney() + totalM02);
            } else {
                storageEntity.setCurrentMoney(totalM02);
            }
            // 库存storage变动
            systemStorageService.updateBySystemIdAndItemId(storageEntity);
        }

        // 流水bill
        PwAccountBillEntity billEntity = new PwAccountBillEntity();
        // 1.ID
        billEntity.setId(Tools.getNewUUID());
        // 2.车站编号
        billEntity.setSystemId(mainEntity.getSystemId());
        // 3.单据编号
        billEntity.setAccountId(mainEntity.getAccountId());
        // 4.单据类型 (查数据字典)
        billEntity.setType(mainEntity.getType());
        // 5.物品Id
        billEntity.setItemId(storageEntity.getItemId());
        // 6.物品状态
        billEntity.setStatus(storageEntity.getStatus());
        // 7.操作类型 (查数据字典)  作废 0;  审核 2
        billEntity.setOperType(PwConstant.BILL_OPER_TYPE_CHECK);
        // 8.出入库标识
        billEntity.setInoutF(PwConstant.BILL_INOUT_TYPE_IN);
        // 9.操作金额
        billEntity.setOperMoney(totalM02);
        // 10.剩余金额 = 库存实际金额
        billEntity.setMoneyLeft(storageEntity.getCurrentMoney());
        // 11.审核员 == Main主表的审核人
        billEntity.setCheckOper(mainEntity.getCheckOper());
        // 12.审核时间 == Main主表的审核时间
        billEntity.setCheckDate(mainEntity.getCheckDate());
        accountBillService.add(billEntity);

        mainEntity.setStatus(PwConstant.PW_ACCOUNTID_STATUS_CHECK);
        accountMainService.update(mainEntity);
    }

    /*
     * @Author:  libs
     * @Date:    2018/8/3  15:58
     * @Description: 作废回收设备票款
     * @params: accountId 要作废的单据编号
     **/
    @Override
    public void invalidCollectEquipmentMoney(String accountId) throws Exception {
        // 查询要作废的单据
        PwAccountMainEntity mainEntity = accountMainDao.selectByAccountId(accountId);
        if (mainEntity == null) {
            throw new BusinessException("查询不到编号为：“" + accountId + "” 的单据！");
        }
        // 单据作废
        mainEntity.invalid();

        // 回滚库存，出库操作
        // 票款出库总额
        double totalM02 = Double.valueOf(mainEntity.getExt2());
        // 物品ID 票款
        String itemId = "M02";

        // 更新的库存，先查询库存总量，计算实际库存
        PwSystemStorageEntity storageEntity = systemStorageService.queryStorageBySystemIdAndItemId(mainEntity.getSystemId(), itemId);
        // 如果库存中不存在抛出异常
        if (storageEntity == null) {
            throw new BusinessException("编号为 “" + itemId + "” 的物品库存不存在！");
        } else {
            // 设置当前金额
            if (storageEntity.getCurrentMoney() != null) {
                storageEntity.setCurrentMoney(storageEntity.getCurrentMoney() - totalM02);
            } else {
                storageEntity.setCurrentMoney(0 - totalM02);
            }
            // 更新库存前检查库存
            if (storageEntity.getCurrentMoney() < 0) {
                throw new BusinessException("编号为 “" + itemId + "” 的物品库存不足，无法作废！");
            }
            // 库存storage变动
            systemStorageService.updateBySystemIdAndItemId(storageEntity);
        }

        // 流水bill
        PwAccountBillEntity billEntity = new PwAccountBillEntity();
        // 1.ID
        billEntity.setId(Tools.getNewUUID());
        // 2.车站编号
        billEntity.setSystemId(mainEntity.getSystemId());
        // 3.单据编号
        billEntity.setAccountId(mainEntity.getAccountId());
        // 4.单据类型 (查数据字典)
        billEntity.setType(mainEntity.getType());
        // 5.物品Id
        billEntity.setItemId(storageEntity.getItemId());
        // 6.物品状态
        billEntity.setStatus(storageEntity.getStatus());
        // 7.操作类型 (查数据字典)  作废 0;  审核 2
        billEntity.setOperType(PwConstant.BILL_OPER_TYPE_INVALID);
        // 8.出入库标识
        billEntity.setInoutF(PwConstant.BILL_INOUT_TYPE_OUT);
        // 9.操作金额
        billEntity.setOperMoney(totalM02);
        // 10.剩余金额 = 库存实际金额
        billEntity.setMoneyLeft(storageEntity.getCurrentMoney());
        // 11.审核员 == Main主表的作废人
        billEntity.setCheckOper(mainEntity.getInvalidOper());
        // 12.审核时间 == Main主表的作废时间
        billEntity.setCheckDate(mainEntity.getInvalidDate());
        accountBillService.add(billEntity);

        // 更新单据
        accountMainDao.updateMainEntityBtAccountId(mainEntity);

    }

    /*
     * @Author:  liyang
     * @Date:    2018/8/2  14:16
     * @Description:查询  起始时间     终止时间内   售票员      单据种类     售票员配票款        type=23
     * @params:          startTime   endTime    sellerId   type       售票员上下班交票款   type=14
     **/
    @Override
    public List<PwAccountMainEntity> findStartAndEndTimeSellerIdMainEntity(PwAccountMainEntity mainEntity) {
        return accountMainDao.findStartAndEndTimeSellerIdMainEntity(mainEntity);
    }

}
